//
//  STAdmobManager.swift
//  iPhone
//
//  Created by Toj on 3/30/23.
//

import UIKit

/*
 * 开屏/ 插页/ 激励/ 插页激励
 * 共性:
 * 1. 都是全屏的互斥关系
 */
public class STAdmobManager: NSObject {
    static let manager = STAdmobManager()
    private override init() {
        super.init()
        registerNotification()
    }
    
    var isShowing = false { didSet {
        print("-->toj: isShowing:\(isShowing)")
    } }
    
    /* 待上报广告 */
    private var _reportAdmobModel: STAdmobModel?
    var hasReport: Bool {
        return _reportAdmobModel != nil
    }
    
    public func cancelReport() {
        guard _reportAdmobModel != nil else { return }
        _reportAdmobModel = nil
        DispatchQueue.main.asyncAfter(deadline: .now()+0.2) {
            print("-->toj: showToast Ad login cancel")
            // UIApplication.shared.keyWindow?.showToast(message: "Ad_login_cancel".localized())
        }
    }
    
    private var mapTable: [String: STAdmobProtocol] = [:]
    func getAdObject(admobModel: STAdmobModel) -> STAdmobProtocol? {
        let adName = admobModel.model.adName
        if let admobObject = mapTable[adName] {
            return admobObject
        }
        var admobObject: STAdmobProtocol?
        switch admobModel.model {
        case .native:
            admobObject = STNativeAdmobObject()
        case .admob:
            admobObject = STInterstitialAdmobObject()
        case .admobAppOpen:
            admobObject = STAppOpenAdmobObject()
        case .admobRewarded:
            admobObject = STRewardedAdmobObject()
        default:
            break
        }
        if admobObject != nil {
            mapTable[adName] = admobObject
        }
        admobObject?.delegate = self
        return admobObject
    }
    
    private var _triggerCount = 0
    var triggerCount: Int {
        get {
            if _triggerCount == 0 {
                let count = STDiskManager.manager.cache(key: .interstitialAdTriggerCount)
                _triggerCount = Int(count) ?? 0
            }
            return _triggerCount
        }
        set {
            _triggerCount = newValue
            STDiskManager.manager.setCache(key: .interstitialAdTriggerCount, value: String(newValue))
        }
    }
    
    private var _triggerTime: TimeInterval = 0
    var triggerTime: TimeInterval {
        get {
            if _triggerTime == 0 {
                let count = STDiskManager.manager.cache(key: .interstitialAdTriggerTime)
                _triggerTime = TimeInterval(count) ?? 0
            }
            return _triggerTime
        }
        set {
            _triggerTime = newValue
            STDiskManager.manager.setCache(key: .interstitialAdTriggerTime, value: String(newValue))
        }
    }
    
    private var _previousTime: CFAbsoluteTime = 0 // 全屏广告触发时间
    private var _timeInterval: CFAbsoluteTime = 10 // 全屏广告触发时间间隔
    private var _isDidEnterBackground = false
    
    private var _window: UIWindow?
    private weak var _adViewController: UIViewController?
}

public extension STAdmobManager {
    
    func isTriggerInterstitial(admobModel: STAdmobModel) -> Bool {
        let numberInterval = admobModel.numberInterval
        print("-->toj: 数量count: \(triggerCount), interval: \(numberInterval)")
        if !checkIntervalNumbers(number: numberInterval) {
            print("-->toj: 数量限制")
            return false
        }
        
        let timeInterval = admobModel.timeInterval * 60
        print("-->toj: 时间time: \(triggerTime), interval: \(timeInterval)")
        if !checkIntervalTimes(time: timeInterval) {
            print("-->toj: 时间限制current: \(CFAbsoluteTimeGetCurrent())")
            return false
        }
        
        print("-->toj: 触发广告 -- count:\(triggerCount), interval: \(numberInterval) time:\(triggerTime), interval: \(timeInterval)")
        triggerCount = 1
        triggerTime = CFAbsoluteTimeGetCurrent()
        print("-->toj: 触发广告 -- triggerCount:\(triggerCount) triggerTime:\(triggerTime)")
        return true
    }
}

private extension STAdmobManager {
    
    func checkIntervalNumbers(number interval: Int) -> Bool {
        guard interval >= 0 else { return false }
        // 第一次
        if triggerCount == 0 { return true }
        let isTrigger = triggerCount > interval
        triggerCount += 1

        return isTrigger
    }

    func checkIntervalTimes(time interval: TimeInterval) -> Bool {
        guard interval > 0 else { return true }
        
        let currentTime = CFAbsoluteTimeGetCurrent()
        let astrictTime = triggerTime + interval
        let isTrigger = currentTime > astrictTime
        
        return isTrigger
    }
}

public extension STAdmobManager {
    
    /* 启动预加载广告 */
    func launchPreloadCacheAds() {
        /* app启动 预加载 缓存的广告 */
        var dateString = Date().to_string("yyyy-MM-dd HH:mm:ss.SSS")
        print("-->toj: date: \(dateString)")
        if let admobModel = STAdManager.manager.appOpenAdmobModelCache() {
            preloadCacheAd(admobModel: admobModel)
        }
        
        /* app启动 预加载 缓存的广告 */
        if let admobModel = STAdManager.manager.rewardAdmobModelCache() {
            preloadCacheAd(admobModel: admobModel)
        }
        dateString = Date().to_string("yyyy-MM-dd HH:mm:ss.SSS")
        print("-->toj: date: \(dateString)")
    }
    
    /* 预加载 广告对象 */
    func preloadCacheAd(admobModel: STAdmobModel) {
        guard admobModel.model != .unknown else { return }
        
        let adObject = getAdObject(admobModel: admobModel)
        adObject?.preloadCacheAd(admobModel: admobModel)
    }
    
    /*
     * 读取是否有 预加载完成的 广告对象
     */
    func isPreparedAd(admobModel: STAdmobModel) -> Bool {
        guard admobModel.model != .unknown else { return false }
        
        let adObject = getAdObject(admobModel: admobModel)
        return adObject?.isPreparedAd(admobModel: admobModel) ?? false
    }
    
    /* 更新预加载 广告数据 并且预加载 广告对象 */
    func replacePreloadCacheAd(admobModel: STAdmobModel, completion: ((_ isSuccess: Bool)->Void)?)  {
        guard admobModel.model != .unknown else { return }
        
        let adObject = getAdObject(admobModel: admobModel)
        adObject?.replacePreloadCacheAd(admobModel: admobModel, completion: completion)
    }
    
    /*
     * 预加载 广告对象,
     * 有预加载 广告对象: 待展示
     * 无预加载 广告对象: 加载 广告对象, 加载完后缓存广告对象 待展示
     */
    func preloadAd(admobModel: STAdmobModel, completion: ((_ isSuccess: Bool)->Void)?) {
        print("-->toj: preloadAd(admobModel: STAdmobModel, completio")
        guard admobModel.model != .unknown else {
            completion?(false)
            return
        }
        
        if isShowing {
            completion?(false)
            return
        }
        isShowing = true
        let adObject = getAdObject(admobModel: admobModel)
        adObject?.preloadAd(admobModel: admobModel) { [weak self] isSuccess in
            self?.isShowing = isSuccess
            completion?(isSuccess)
        }
    }
    
    /* 加载新广告对象 */
    func loadAd(admobModel: STAdmobModel, completion: ((_ isSuccess: Bool)->Void)?) {
        guard admobModel.model != .unknown else {
            completion?(false)
            return
        }
        
        if isShowing {
            completion?(false)
            return
        }
        isShowing = true
        
        let adObject = getAdObject(admobModel: admobModel)
        adObject?.loadAd(admobModel: admobModel) { [weak self] isSuccess in
            self?.isShowing = isSuccess
            completion?(isSuccess)
        }
    }
    
    /* 展示 广告对象 */
    func presentAd(admobModel: STAdmobModel) {
        print("-->toj: ****************************M: \(admobModel.model)")
        guard admobModel.model != .unknown else { return }
        
        let vc = setupAdController()
        if _window == nil {
            _window = UIWindow()
        }
        _adViewController = vc
        
        _window?.rootViewController = vc
        showAd(alpha: 0)
        let adObject = getAdObject(admobModel: admobModel)
        adObject?.presentAd(from: vc)
    }
    
    func setupWindow() -> UIWindow {
        let window = UIWindow()
        window.frame = UIScreen.main.bounds
        return window
    }
    
    func setupAdController() -> UIViewController {
        let vc = STAdmobViewController()
        vc.view.backgroundColor = .clear
        return vc
    }
    
    func showAd(alpha: CGFloat = 1) {
        _window?.windowLevel = .statusBar + 1
        _window?.isHidden = false
        _window?.alpha = alpha
    }
    
    func hideAd() {
        ///来个渐显动画
        UIView.animate(withDuration: 0.25) {
            self.hidingAd()
        } completion: { finished in
            self.removeAd()
        }
    }
    
    func hidingAd() {
        _window?.alpha = 0
    }
    
    func removeAd() {
        let views = _window?.subviews ?? []
        views.forEach { view in
            view.removeFromSuperview()
        }
        _window?.isHidden = true
        _window = nil
    }
}

/* 接口响应 */
private extension STAdmobManager {
    
    // 激励广告上报 响应
    func responseReport(admobModel: STAdmobModel, result: STAdReportModel) {
    }
    
    func responseAppOpenAds(admobModels: [STAdmobModel]) {
        var successModel: STAdmobModel?
        print("-->toj: 更新开屏广告")
        admobModels.forEach { admobModel in
            replacePreloadCacheAd(admobModel: admobModel) { isSuccess in
                guard isSuccess else { return }
                guard successModel == nil else { return }
                successModel = admobModel
                print("-->toj: 第一个新的开屏广告返回:\(admobModel.model)")
                STAdManager.manager.setAppOpenAdmobModelCache(admobModel: admobModel)
            }
        }
    }
}

/* 接口请求 */
public extension STAdmobManager {
    
    func requestAppOpenAd() {
        print("-->toj: 请求新的开屏广告")
        STAdManager.manager.requestAppOpenAds(completion: { [weak self] admobModels in
            self?.responseAppOpenAds(admobModels: admobModels)
        })
    }
    
    func requestHistoryReport(admobModel: STAdmobModel?) {
        guard let reportAdmobModel = admobModel else { return }
        requestReport(admobModel: reportAdmobModel)
    }
    
    func requestReport(admobModel: STAdmobModel) {
        guard STUserCenter.default.isLogin else {
            _reportAdmobModel = admobModel
            // ds_admob(model: admobModel, action: "", label: "")
            //            let state: STRewardState = .unlogin
            //            STRewardView.shared.show(state: state, title: "login".localized(), tip: state.tipString)
            print("-->toj: 弹出登录框")
            return
        }
        
        _reportAdmobModel = nil
        STAdManager.manager.requestRewardReport(admobModel: admobModel) { [weak self] result in
            self?.responseReport(admobModel: admobModel, result: result)
        }
    }
}

extension STAdmobManager: STAdmobObjectDelegate {
    public func admobObjectDidPresentContent(_ admobObject: STAdmobObject, admobModel: STAdmobModel?) {
        showAd()
    }
    
    public func admobObject(_ admobObject: STAdmobObject, admobModel: STAdmobModel?, didFailToPresentFullScreenContent error: Error?) {
        
    }
    
    public func admobObjectWillDismissComplete(_ admobObject: STAdmobObject, admobModel: STAdmobModel?, showedTime: TimeInterval) {
        hideAd()
    }
    
    public func admobObjectDidDismissComplete(_ admobObject: STAdmobObject, admobModel: STAdmobModel?) {
        guard let _ = admobModel else { return }
       // ds_rewardBuried(rewardAD: reward, action: .show, label: .failure, value: reward.ds_value)
        isShowing = false
        _previousTime = CFAbsoluteTimeGetCurrent()
    }
    
    public func admobObjectDidRecordClick(_ admobObject: STAdmobObject, admobModel: STAdmobModel?) {
        
    }
}

private extension STAdmobManager {
    
    // 已经进入后台
    @objc func didEnterBackground(sender: Notification) {
        print("-->toj: class:\(cm_objectName), func:" + #function)
        _isDidEnterBackground = true
    }
    
    // 将要进入前台
    @objc func didBecomeActive(sender: Notification) {
        print("-->toj: class:\(cm_objectName), func:" + #function)
        guard _isDidEnterBackground else {
            return
        }
        _isDidEnterBackground = false
        guard !isShowing else { return }
        
        let currentTime = CFAbsoluteTimeGetCurrent()
        let interval = currentTime - _previousTime
        print("-->toj: interval: \(interval)")
        guard interval >= _timeInterval else { return }
        
        guard let admobModel = STAdManager.manager.appOpenAdmobModelCache() else { return }
        let isPreparedAd = STAdmobManager.manager.isPreparedAd(admobModel: admobModel)
        guard isPreparedAd else {
            STAdmobManager.manager.requestAppOpenAd()
            return
        }
        
        STAdmobManager.manager.presentAd(admobModel: admobModel)
        STAdmobManager.manager.requestAppOpenAd()
    }
}

private extension STAdmobManager {
    
    func registerNotification() {
        print("-->toj: func: " + #function)
        
        // 已经进入后台
        NotificationCenter.default.addObserver(self, selector: #selector(didEnterBackground(sender:)), name: UIApplication.didEnterBackgroundNotification, object: nil)
        
        // 将要进入前台
        NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive(sender:)), name: UIApplication.didBecomeActiveNotification, object: nil)
    }
}


/* 埋点 */
extension STAdmobManager {
    
    func ds_admob(model: STAdmobModel, action: String, label: String, value: String = "", ext: [String: String]? = nil) {
        
    }
}
